package com.xhtt.modules.task.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhtt.common.exception.RRException;
import com.xhtt.common.file.FileInfoModel;
import com.xhtt.common.utils.CopyUtils;
import com.xhtt.common.utils.PageUtils;
import com.xhtt.common.utils.Query;
import com.xhtt.modules.cfg.entity.CfgTaskInfo;
import com.xhtt.modules.cfg.entity.CfgTaskSub;
import com.xhtt.modules.cfg.entity.CfgWarnTask;
import com.xhtt.modules.cfg.service.CfgTaskInfoService;
import com.xhtt.modules.cfg.service.CfgTaskSubService;
import com.xhtt.modules.cfg.service.CfgWarnTaskService;
import com.xhtt.modules.sys.entity.SysUserEntity;
import com.xhtt.modules.task.dao.TaskPotPlanMapper;
import com.xhtt.modules.task.entity.*;
import com.xhtt.modules.task.model.pot.ArrangeModel;
import com.xhtt.modules.task.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 罐计划 服务实现类
 * </p>
 *
 * @author feipc
 * @since 2019-03-05
 */
@Service
public class TaskPotPlanServiceImpl extends ServiceImpl<TaskPotPlanMapper, TaskPotPlan> implements TaskPotPlanService {

    @Autowired
    private CfgTaskInfoService taskInfoService;
    @Autowired
    private CfgTaskSubService taskSubService;
    @Autowired
    private TaskPotTaskService taskPotTaskService;
    @Autowired
    private TaskPotTaskStepService taskPotTaskStepService;
    @Autowired
    private CfgWarnTaskService warnTaskService;
    @Autowired
    private TaskPotTaskStepService taskPotStepService;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private TaskPotSeoService taskPotSeoService;
    @Autowired
    private TaskPotSeoLogService taskPotSeoLogService;

    @Override
    public PageUtils planList(Map<String, Object> params, SysUserEntity user) {
        Object status = params.get("status");
        if (null != status && status.toString().equals("2"))//分配任务页面，执行班组的人可以看到安排给自己班组的任务，其他人看不到
        {
            params.put("teamId", user.getTeamId());
        }
        Page<TaskPotPlan> page = new Query<TaskPotPlan>(params).getPage();
        page.setRecords(baseMapper.planList(page, params));
        return new PageUtils(page);
    }

    @Override
    public void addPlan(TaskPotPlan taskPotPlan) {
        //设置主任务（计划）名称
        taskPotPlan.setTaskName(taskPotPlan.getPotExportName() + "→" + taskPotPlan.getPotImportName());
        taskPotPlan.setStatus(1);
        this.save(taskPotPlan);
    }

    @Override
    public void deletePlan(List<Integer> planIds) {
        this.removeByIds(planIds);
    }

    @Override
    public void updatePlan(TaskPotPlan taskPotPlan) {
        Integer planId = taskPotPlan.getId();
        if (null == planId) {
            throw new RRException("参数有误");
        }
        TaskPotPlan db = this.getById(planId);
        if (null == db) {
            throw new RRException("对象不存在");
        }
        List<FileInfoModel> photoFileList = taskPotPlan.getPhotoFiles();
        if (CollectionUtils.isNotEmpty(photoFileList)) {
            taskPotPlan.setPhoto(JSON.toJSONString(photoFileList));
        } else {
            taskPotPlan.setPhoto(JSON.toJSONString(Collections.EMPTY_LIST));
        }
        CopyUtils.copyProperties(taskPotPlan, db);
        this.updateById(db);
    }

    @Override
    public TaskPotPlan getPlan(Integer planId) {
        TaskPotPlan taskPotPlan = this.getById(planId);
        if (null == taskPotPlan) {
            throw new RRException("对象不存在");
        }
        String photo = taskPotPlan.getPhoto();
        if (StringUtils.isNotEmpty(photo)) {
            taskPotPlan.setPhotoFiles(JSON.parseArray(photo, FileInfoModel.class));
        }

        return taskPotPlan;
    }

    @Override
    public ArrangeModel getArrangeInfo(Integer id) {
        ArrangeModel model = new ArrangeModel();
        TaskPotPlan taskPotPlan = this.getById(id);
        if (null == taskPotPlan) {
            throw new RRException("对象不存在");
        }

        model.setPlanId(id);
        model.setMainTaskName(taskPotPlan.getTaskName());
        model.setProductId(taskPotPlan.getProductId());
        model.setProductName(taskPotPlan.getProductName());
        CfgTaskInfo cfgTaskInfo = taskInfoService.getOne(new LambdaQueryWrapper<CfgTaskInfo>().eq(CfgTaskInfo::getName, "倒罐").select(CfgTaskInfo::getId));
        if (null == cfgTaskInfo) {
            throw new RRException("计划任务配置有误");
        }
        List<TaskPotTask> tasks = new ArrayList<>();
        //找到配置好的要做的任务
        List<CfgTaskSub> taskSubList = taskSubService.list(new LambdaQueryWrapper<CfgTaskSub>().eq(CfgTaskSub::getTaskId, cfgTaskInfo.getId()));

        TaskPotTask potTask;
        for (CfgTaskSub cfgTaskSub : taskSubList) {
            if (cfgTaskSub.getStatus().intValue() != 1) {
                continue;//删除状态的就不管
            }
            potTask = new TaskPotTask();
            potTask.setName(cfgTaskSub.getName());
            potTask.setType(cfgTaskSub.getType());
            //排管任务进一步处理，其他任务就不用处理了
            if (cfgTaskSub.getType().intValue() == 1) {
                // 遍历产品,设置连接的头尾
                List<TaskPotTaskStep> stepList = new ArrayList<>();
                //构造输出罐
                TaskPotTaskStep stepPotStart = new TaskPotTaskStep();
                stepPotStart.setType(1);//1罐2硬3泵4码5软
                stepPotStart.setTypeId(taskPotPlan.getPotExportId());
                stepPotStart.setTypeName(taskPotPlan.getPotExportName());
                //构造输入罐
                TaskPotTaskStep stepPotEnd = new TaskPotTaskStep();
                stepPotEnd.setType(1);//1罐2硬3泵4码5软
                stepPotEnd.setTypeId(taskPotPlan.getPotImportId());
                stepPotEnd.setTypeName(taskPotPlan.getPotImportName());

                //设置第一个连接点
                stepList.add(stepPotStart);
                //设置最后一个连接点
                stepList.add(stepPotEnd);

                potTask.setTaskStepList(stepList);
            }
            tasks.add(potTask);
        }
        model.setTasks(tasks);
        return model;
    }

    @Override
    public void arrange(ArrangeModel arrangeModel) {
        Integer planId = arrangeModel.getPlanId();
        List<TaskPotTask> ts = transactionTemplate.execute(transactionStatus -> {
            try {
                TaskPotPlan potPlan = this.getById(planId);
                if (null == potPlan) {
                    throw new RRException("对象不存在");
                }
                potPlan.setStatus(2);//1待安排2待分配3退回4进行中9完成
                potPlan.setTaskName(arrangeModel.getMainTaskName());
                this.updateById(potPlan);//跟新个名字而已
                //
                List<TaskPotTask> tasks = arrangeModel.getTasks();
                tasks.forEach(taskShipTask -> taskShipTask.setPotPlanId(planId));

                //创建之前看一下有没有创建过了小任务 ，有的话全删除，并记录下taskIds，因为后面还要删步骤
                List<TaskPotTask> oldTasks = taskPotTaskService.list(new LambdaQueryWrapper<TaskPotTask>().eq(TaskPotTask::getPotPlanId, planId).select(TaskPotTask::getId));
                if (CollectionUtils.isNotEmpty(oldTasks)) {
                    //取taskIds
                    List<Integer> taskIds = oldTasks.stream().map(taskPotTask -> taskPotTask.getId()).collect(Collectors.toList());
                    //删除tasks
                    taskPotTaskService.removeByIds(taskIds);
                    // 获取steps
//                    List<TaskPotTaskStep> steps = taskPotStepService.list(new LambdaQueryWrapper<TaskPotTaskStep>().in(TaskPotTaskStep::getPotTaskId, taskIds));
                    //还要把steps里面关联的节点还原成未使用
//                    if (CollectionUtils.isNotEmpty(steps)) {
//                        conPointService.releasePotPoint(steps);//业务改了 不需要了
//                    }
                    //删除steps
                    taskPotStepService.remove(new LambdaQueryWrapper<TaskPotTaskStep>().in(TaskPotTaskStep::getPotTaskId, taskIds));
                }
                taskPotTaskService.saveBatch(tasks);//创建小任务

                //但是要保存第一个和最后一个节点，为下一步用
                for (TaskPotTask potTask : tasks) {
                    if (1 == potTask.getType().intValue()) {
                        List<TaskPotTaskStep> taskPotTaskSteps = potTask.getTaskStepList();
                        taskPotTaskSteps.forEach(pp -> pp.setPotTaskId(potTask.getId()));
                        taskPotTaskStepService.saveBatch(taskPotTaskSteps);//保存链接任务步骤
                    }
                }

                return tasks;

            } catch (Throwable e) {
                e.printStackTrace();
                transactionStatus.setRollbackOnly();
                return null;
            }
        });
        if (null == ts) {
            throw new RRException("处理异常");
        }
    }

    @Override
    public void back(TaskPotPlan plan) {
        TaskPotPlan pp = new TaskPotPlan();
        pp.setId(plan.getId());
        pp.setStatus(3);//1待安排2待分配3退回4进行中9完成
        pp.setBackReason(plan.getBackReason());
        this.updateById(pp);

        //狗日的 分配的时候才保存软管连接 ，所以回退不涉及了
        //解放管子和泵
//        taskExecutor.execute(() -> {
//            TaskPotTask task = taskPotTaskService.getOne(new LambdaQueryWrapper<TaskPotTask>().eq(TaskPotTask::getPotPlanId, plan.getId()).eq(TaskPotTask::getType, 1).select(TaskPotTask::getId));//拿到排管任务id
//            if (null != task) {
//                //然后拿节点
//                List<TaskPotTaskStep> steps = taskPotStepService.list(new LambdaQueryWrapper<TaskPotTaskStep>().eq(TaskPotTaskStep::getPotTaskId, task.getId()).in(TaskPotTaskStep::getType, Arrays.asList(new Integer[]{2, 3, 5})));
//                for (TaskPotTaskStep step : steps) {
//                    if (step.getType().intValue() == 2) {
//                        CfgTubeInfo tube = new CfgTubeInfo();
//                        tube.setUsed(0);
//                        cfgTubeInfoService.update(tube, new LambdaQueryWrapper<CfgTubeInfo>().eq(CfgTubeInfo::getId, step.getTypeId()));
//                    } else if (step.getType().intValue() == 3) {
//                        CfgPumpInfo pump = new CfgPumpInfo();
//                        pump.setUsed(0);
//                        cfgPumpInfoService.update(pump, new LambdaQueryWrapper<CfgPumpInfo>().eq(CfgPumpInfo::getId, step.getTypeId()));
//                    } else if (step.getType().intValue() == 5) {
//                        CfgHoseInfo hose = new CfgHoseInfo();
//                        hose.setUsed(0);
//                        cfgHoseInfoService.update(hose, new LambdaQueryWrapper<CfgHoseInfo>().eq(CfgHoseInfo::getId, step.getTypeId()));
//                    }
//                }
//            }
//
//        });
    }

    @Override
    public PageUtils seoList(Map<String, Object> params) {
        Page<TaskPotSeo> page = new Query<TaskPotSeo>(params).getPage();
        List<TaskPotSeo> list = baseMapper.seoList(page, params);
        for (TaskPotSeo seo : list) {
            Set teamNames = new HashSet();
            if (StringUtils.isNotEmpty(seo.getHoseTeamName())) {
                teamNames.add(seo.getHoseTeamName());
            }
            if (StringUtils.isNotEmpty(seo.getCcrTeamName())) {
                teamNames.add(seo.getCcrTeamName());
            }
            if (StringUtils.isNotEmpty(seo.getBallTeamName())) {
                teamNames.add(seo.getBallTeamName());
            }
            if (CollectionUtils.isNotEmpty(teamNames)) {
                seo.setTeamName(StringUtils.join(teamNames, "，"));
            }
        }
        List<CfgWarnTask> warnTaskList = warnTaskService.list();
        Map<String, Integer> warnStartMap = new HashMap<>();
        Map<String, Integer> warnFinishMap = new HashMap<>();
        for (CfgWarnTask wt : warnTaskList) {
            warnStartMap.put(wt.getPlan() + "-" + wt.getPlanType() + "-" + wt.getTaskType(), wt.getTime1());
            warnFinishMap.put(wt.getPlan() + "-" + wt.getPlanType() + "-" + wt.getTaskType(), wt.getTime2());
        }
        if (warnStartMap.size() != 0) {
            for (TaskPotSeo seo : list) {
                Integer ballTime = warnStartMap.get("pot-1-3");//这里数据库配好了 通球就是3，所以写死了
                if (null == ballTime || ballTime.intValue() < 0) {
                    continue;
                }
                LocalDateTime ballPlanStartDate = seo.getBallPlanStartTime();
                LocalDateTime ballStartTime = seo.getBallStartTime();
                if (null != ballPlanStartDate && null != ballStartTime) {
                    LocalDateTime deadline = ballPlanStartDate.plusMinutes(ballTime);
                    if (ballStartTime.compareTo(deadline) > 0) {
                        seo.setBallStartTimeIfWarn(1);
                    }
                }

                Integer hoseTime = warnStartMap.get("pot-1-1");//这里数据库配好了 管线就是1，所以写死了
                if (null == hoseTime || hoseTime.intValue() < 0) {
                    continue;
                }
                LocalDateTime hosePlanStartDate = seo.getHosePlanStartTime();
                LocalDateTime hoseStartTime = seo.getHoseStartTime();
                if (null != hosePlanStartDate && null != hoseStartTime) {
                    LocalDateTime deadline = hosePlanStartDate.plusMinutes(hoseTime);
                    if (hoseStartTime.compareTo(deadline) > 0) {
                        seo.setHoseStartTimeIfWarn(1);
                    }
                }
            }
        }
        if (warnFinishMap.size() != 0) {
            for (TaskPotSeo seo : list) {
                Integer ballTime = warnFinishMap.get("pot-1-3");//这里数据库配好了 通球就是3，所以写死了
                if (null == ballTime || ballTime.intValue() < 0) {
                    continue;
                }
                LocalDateTime ballFinishTime = seo.getBallFinishTime();
                LocalDateTime ballStartTime = seo.getBallStartTime();
                if (null != ballFinishTime && null != ballStartTime) {
                    LocalDateTime deadline = ballStartTime.plusMinutes(ballTime);
                    if (ballFinishTime.compareTo(deadline) > 0) {
                        seo.setBallFinishTimeIfWarn(1);
                    }
                }
                Integer hoseTime = warnFinishMap.get("pot-1-1");//这里数据库配好了 管线就是1，所以写死了
                if (null == hoseTime || hoseTime.intValue() < 0) {
                    continue;
                }
                LocalDateTime hoseFinishTime = seo.getHoseFinishTime();
                LocalDateTime hoseStartTime = seo.getHoseStartTime();
                if (null != hoseFinishTime && null != hoseStartTime) {
                    LocalDateTime deadline = hoseStartTime.plusMinutes(hoseTime);
                    if (hoseFinishTime.compareTo(deadline) > 0) {
                        seo.setHoseFinishTimeIfWarn(1);
                    }
                }
            }
        }
        page.setRecords(list);
        return new PageUtils(page);
    }

    @Override
    public TaskPotSeo dataToSeo(Integer potPlanId) {
        return baseMapper.dataToSeo(potPlanId);
    }

    @Override
    @Transactional
    public void seoEdit(TaskPotSeo seo, SysUserEntity user) {
        taskPotSeoService.updateById(seo);
        TaskPotSeoLog seoLog = new TaskPotSeoLog();
        seoLog.setId(seo.getId());
        seoLog.setUserId(user.getUserId().intValue());
        seoLog.setUserName(user.getName());
        taskPotSeoLogService.save(seoLog);
    }

//    public synchronized void updateSteps(List<SuperTaskStep> taskSteps,Integer taskId)
//    {
//        //待更新使用状态的硬管id
//        List<Integer> upTubeIds = new ArrayList<>();
//        //待更新使用状态的泵id
//        List<Integer> upPumpIds = new ArrayList<>();
//        //待更新使用状态的软管id
//        List<Integer> upHoseIds = new ArrayList<>();
//        if (CollectionUtils.isNotEmpty(taskSteps)) {
//            //获取所有可用硬管Id
//            List<Integer> tubeIds = new ArrayList<>();//cfgTubeInfoService.list(new LambdaQueryWrapper<CfgTubeInfo>().eq(CfgTubeInfo::getStatus, 1).eq(CfgTubeInfo::getUsed, 0).select(CfgTubeInfo::getId)).stream().map(cfgTubeInfo -> cfgTubeInfo.getId()).collect(Collectors.toList());
//            //获取所有可用泵
//            List<Integer> pumpIds = new ArrayList<>();//cfgPumpInfoService.list(new LambdaQueryWrapper<CfgPumpInfo>().eq(CfgPumpInfo::getStatus, 1).eq(CfgPumpInfo::getUsed, 0).select(CfgPumpInfo::getId)).stream().map(cfgPumpInfo -> cfgPumpInfo.getId()).collect(Collectors.toList());
//            //获取所有可用软管
//            List<Integer> hoseIds = new ArrayList<>();//cfgHoseInfoService.list(new LambdaQueryWrapper<CfgHoseInfo>().eq(CfgHoseInfo::getStatus, 1).eq(CfgHoseInfo::getUsed, 0).select(CfgHoseInfo::getId)).stream().map(cfgHoseInfo -> cfgHoseInfo.getId()).collect(Collectors.toList());
//
//            List<TaskPotTaskStep> ll = new ArrayList<>();
//            for (SuperTaskStep tt : taskSteps) {
////                potTaskStep.getClass().isInstance()
//
//                //判断连接点是否可用  1罐2硬3泵4码5软
//                int conType = tt.getType().intValue();
//                Integer conTypeId = tt.getTypeId();
//                if (2 == conType) {
//                    if (!tubeIds.contains(conTypeId)) {
//                        throw new RRException(tt.getTypeName() + " 已使用，请重新选择");
//                    }
//                    upTubeIds.add(conTypeId);
//                } else if (3 == conType) {
//                    if (!pumpIds.contains(conTypeId)) {
//                        throw new RRException(tt.getTypeName() + " 已使用，请重新选择");
//                    }
//                    upPumpIds.add(conTypeId);
//                } else if (5 == conType) {
//                    if (!hoseIds.contains(conTypeId)) {
//                        throw new RRException(tt.getTypeName() + " 已使用，请重新选择");
//                    }
//                    upHoseIds.add(conTypeId);
//                }
//
//                TaskPotTaskStep potTaskStep = (TaskPotTaskStep) tt;
//                potTaskStep.setPotTaskId(taskId);
//
//                ll.add(potTaskStep);
//            }
//            taskPotStepService.saveBatch(ll);//保存链接任务步骤
//        }
//
//        //然后把连接点都设为已使用
//        if (CollectionUtils.isNotEmpty(upTubeIds)) {
//            cfgTubeInfoService.updateUsed(upTubeIds);
//        }
//        if (CollectionUtils.isNotEmpty(upPumpIds)) {
//            cfgPumpInfoService.updateUsed(upTubeIds);
//        }
//        if (CollectionUtils.isNotEmpty(upHoseIds)) {
//            cfgHoseInfoService.updateUsed(upTubeIds);
//        }
//    }

}
